package com.sparrow.common.util;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 *  token 生成工具类
 *
 *  基于 HMAC-SHA256 的自定义 token 生成工具，保证 token 防伪、防篡改
 *  HMAC-SHA256 是一种使用密钥和 SHA-256 哈希函数生成的消息认证码（MAC），用于验证数据完整性和身份真实性。
 *  最终签名格式
 *  <Base64(payload)>.<signature>
 *  payload=playerId:timestamp
 */
public class TokenUtil {
    private static final String SECRET_KEY = PropertiesUtil.getPropertyOrDefault("token_secret_key", "your-very-secret-key");

    /**
     * 为playerId生成token
     */
    public static String createToken(String key) {
        long timestamp = System.currentTimeMillis();
        String payload = key + ":" + timestamp;
        String sign = null;
        try {
            sign = hmacSha256(payload, SECRET_KEY);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return Base64.getEncoder().encodeToString(payload.getBytes(StandardCharsets.UTF_8)) + "." + sign;
    }

    public static String hmacSha256(String data, String key) {
        Mac mac = null;
        try {
            mac = Mac.getInstance("HmacSHA256");
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        SecretKeySpec spec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
        try {
            mac.init(spec);
        } catch (InvalidKeyException e) {
            throw new RuntimeException(e);
        }
        byte[] result = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return bytesToHex(result);
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) sb.append(String.format("%02x", b));
        return sb.toString();
    }

    public static String validateToken(String token) {
        String[] parts = token.split("\\.");
        if (parts.length != 2) return null;

        String payloadBase64 = parts[0];
        String sign = parts[1];

        String payload = new String(Base64.getDecoder().decode(payloadBase64), StandardCharsets.UTF_8);
        String expectedSign = hmacSha256(payload, SECRET_KEY);
        if (!expectedSign.equals(sign)) return null;

        String[] fields = payload.split(":");
        if (fields.length != 2) return null;

        String key = fields[0];
        long timestamp = Long.parseLong(fields[1]);

        // 30分钟有效期
        if (System.currentTimeMillis() - timestamp > 30 * 60 * 1000) {
            return null;
        }

        return key;
    }


    public static void main(String[] args) {
        String token = createToken("123456");
        System.out.println("Token: " + token);

        String result = validateToken(token);
        if (result != null) {
            System.out.println("验证通过，playerId = " + result);
        } else {
            System.out.println("验证失败");
        }
    }

}
